package co.yixiang.modules.adopt.serviceimpl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import co.yixiang.cache.Cache;
import co.yixiang.common.exception.BadRequestException;
import co.yixiang.common.service.impl.BaseServiceImpl;
import co.yixiang.common.utils.FileUtil;
import co.yixiang.common.utils.QueryHelpPlus;
import co.yixiang.dozer.service.IGenerator;
import co.yixiang.modules.adopt.entity.domain.YxAdoptContract;
import co.yixiang.modules.adopt.entity.domain.YxAdoptProduct;
import co.yixiang.modules.adopt.entity.dto.YxAdoptProductDto;
import co.yixiang.modules.adopt.entity.dto.YxAdoptProductQueryCriteria;
import co.yixiang.modules.adopt.entity.vo.YxAdoptProductVo;
import co.yixiang.modules.adopt.mapper.AdoptProductMapper;
import co.yixiang.modules.adopt.service.YxAdoptCategoryService;
import co.yixiang.modules.adopt.service.YxAdoptContractService;
import co.yixiang.modules.adopt.service.YxAdoptFeatureService;
import co.yixiang.modules.adopt.service.YxAdoptProductService;
import co.yixiang.modules.goods.entity.dto.ProductFormatDto;
import co.yixiang.modules.member.entity.vo.YxUserSmallVo;
import co.yixiang.modules.member.service.YxUserService;
import co.yixiang.modules.order.order.entity.enums.OrderTypeEnum;
import co.yixiang.modules.order.order.mapper.StoreOrderMapper;
import co.yixiang.modules.shop.entity.dto.DetailDto;
import co.yixiang.modules.shop.entity.dto.FromatDetailDto;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class YxAdoptProductServiceImpl extends BaseServiceImpl<AdoptProductMapper, YxAdoptProduct> implements YxAdoptProductService {

    @Autowired
    private IGenerator generator;

    @Autowired
    private YxAdoptCategoryService yxAdoptCategoryService;
    @Autowired
    private YxAdoptContractService contractService;
    @Autowired
    private YxAdoptFeatureService featureService;
    @Autowired
    private StoreOrderMapper orderMapper;

    @Autowired
    private YxUserService userService;

    /**
     * 缓存
     */
    @Autowired
    private Cache cache;

    @Override
    public Map<String, Object> queryAllByCateId(YxAdoptProductQueryCriteria criteria, Pageable pageable) {
        getPage(pageable);
        List<YxAdoptProduct> yxAdoptProductList = baseMapper.selectByMyWrapper(criteria.getLng(),criteria.getLat(),QueryHelpPlus.getPredicate(YxAdoptProduct.class, criteria));
        List<YxAdoptProductVo> adoptProductVos = new ArrayList<>(yxAdoptProductList.size());
        yxAdoptProductList.forEach(yxAdoptProduct -> {
            final YxAdoptProductVo yxAdoptProductVo = BeanUtil.copyProperties(yxAdoptProduct, YxAdoptProductVo.class);
            // 分类
            yxAdoptProductVo.setAdoptCategory(yxAdoptCategoryService.getById(yxAdoptProduct.getCateId()));
            // 合同
            //yxAdoptProductVo.setAdoptContractList(contractService.list(new LambdaQueryWrapper<YxAdoptContract>().eq(YxAdoptContract::getCid, yxAdoptProduct.getCateId())));
            // 产品特点
            //yxAdoptProductVo.setAdoptFeatureList(featureService.listByIds(ObjectUtil.isNotEmpty(yxAdoptProductVo.getFeature())? Arrays.stream(yxAdoptProductVo.getFeature().split(",")).collect(Collectors.toList()):new ArrayList<>()));
            // 查询认养该产品的用户
            List<Map<String, Object>> longs = orderMapper.selectYxUserByAdoptAndGoodId(yxAdoptProduct.getId().toString(), OrderTypeEnum.ADOPT.name());
            Map<String, Object> resultMap = new HashMap<>();
            longs.forEach(v -> {
                resultMap.put(v.get("key").toString(),v.get("value"));
            });
            if (CollectionUtil.isNotEmpty(resultMap)) {
                List<YxUserSmallVo> convert = generator.convert(userService.listByIds(resultMap.keySet()), YxUserSmallVo.class);
                convert.forEach(v -> {

                    v.setBuyCount(Integer.parseInt(resultMap.get(v.getUid()).toString()));
                });
                final List<YxUserSmallVo> collect = convert.stream().sorted(Comparator.comparing(YxUserSmallVo::getBuyCount)).collect(Collectors.toList());
                yxAdoptProductVo.setYxUserList(collect);
            }
            adoptProductVos.add(yxAdoptProductVo);
        });
        PageInfo<YxAdoptProductVo> page = new PageInfo<>(adoptProductVos);
        Map<String, Object> map = new LinkedHashMap<>(2);
        map.put("content",page.getList());
        map.put("totalElements", page.getTotal());
        return map;
    }

    @Override
    public YxAdoptProductVo queryAdoptDetail(Long id) {
        final YxAdoptProduct goods = this.getById(id);
        if (ObjectUtil.isEmpty(goods)) {
            throw new BadRequestException("不存在这个认养");
        }
        YxAdoptProductVo yxAdoptProductVo = BeanUtil.copyProperties(goods, YxAdoptProductVo.class);
        // 分类
        yxAdoptProductVo.setAdoptCategory(yxAdoptCategoryService.getById(yxAdoptProductVo.getCateId()));
        // 合同
        yxAdoptProductVo.setAdoptContractList(contractService.list(new LambdaQueryWrapper<YxAdoptContract>().eq(YxAdoptContract::getCid, yxAdoptProductVo.getCateId())));
        // 产品特点
        yxAdoptProductVo.setAdoptFeatureList(featureService.listByIds(ObjectUtil.isNotEmpty(yxAdoptProductVo.getFeature())? Arrays.stream(yxAdoptProductVo.getFeature().split(",")).collect(Collectors.toList()):new ArrayList<>()));
        // 查询认养该产品的用户
        List<Map<String, Object>> longs = orderMapper.selectYxUserByAdoptAndGoodId(yxAdoptProductVo.getId(), OrderTypeEnum.ADOPT.name());
        Map<String, Object> resultMap = new HashMap<>();
        longs.forEach(v -> {
            resultMap.put(v.get("key").toString(),v.get("value"));
        });
        if (CollectionUtil.isNotEmpty(resultMap)) {
            List<YxUserSmallVo> convert = generator.convert(userService.listByIds(resultMap.keySet()), YxUserSmallVo.class);
            convert.forEach(v -> {
                v.setBuyCount(Integer.parseInt(resultMap.get(v.getUid()).toString()));
            });
           convert.sort(Comparator.comparing(YxUserSmallVo::getBuyCount).reversed());
            yxAdoptProductVo.setYxUserList(convert);
        }
        // 增加商品浏览记录
        goods.setBrowse(goods.getBrowse() + 1);
        goods.setPosition(null);
        this.updateById(goods);
        return yxAdoptProductVo;
    }

    @Override
    //@Cacheable
    public Map<String, Object> queryAll(YxAdoptProductQueryCriteria criteria, Pageable pageable) {
        getPage(pageable);
        PageInfo<YxAdoptProduct> page = new PageInfo<>(queryAll(criteria));
        Map<String, Object> map = new LinkedHashMap<>(2);
        map.put("content", generator.convert(page.getList(), YxAdoptProductDto.class));
        map.put("totalElements", page.getTotal());
        return map;
    }


    @Override
    //@Cacheable
    public List<YxAdoptProduct> queryAll(YxAdoptProductQueryCriteria criteria) {
        List<YxAdoptProduct> yxAdoptProductList = baseMapper.selectList(QueryHelpPlus.getPredicate(YxAdoptProduct.class, criteria));
        yxAdoptProductList.forEach(yxAdoptProduct -> {
            yxAdoptProduct.setAdoptCategory(yxAdoptCategoryService.getById(yxAdoptProduct.getCateId()));
            // yxAdoptProduct.setAdoptContract(yxAdoptContractService.getById(yxAdoptProduct.getContract()));
        });
        return yxAdoptProductList;
    }



    @Override
    public void download(List<YxAdoptProductDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (YxAdoptProductDto yxAdoptProduct : all) {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("商品图片", yxAdoptProduct.getImage());
            map.put("轮播图", yxAdoptProduct.getSliderImage());
            map.put("商品名称", yxAdoptProduct.getAdoptName());
            map.put("商品简介", yxAdoptProduct.getAdoptInfo());
            map.put("关键字", yxAdoptProduct.getKeyword());
            map.put("产品条码（一维码）", yxAdoptProduct.getBarCode());
            map.put("分类id", yxAdoptProduct.getCateId());
            map.put("商品价格", yxAdoptProduct.getPrice());
            map.put("会员价格", yxAdoptProduct.getVipPrice());
            map.put("市场价", yxAdoptProduct.getOtPrice());
            map.put("邮费", yxAdoptProduct.getPostage());
            map.put("单位名", yxAdoptProduct.getUnitName());
            map.put("排序", yxAdoptProduct.getSort());
            map.put("销量", yxAdoptProduct.getSales());
            map.put("库存", yxAdoptProduct.getStock());
            map.put("状态（0：未上架，1：上架）", yxAdoptProduct.getIsShow());
            map.put("是否热卖", yxAdoptProduct.getIsHot());
            map.put("是否优惠", yxAdoptProduct.getIsBenefit());
            map.put("是否精品", yxAdoptProduct.getIsBest());
            map.put("是否新品", yxAdoptProduct.getIsNew());
            map.put("产品描述", yxAdoptProduct.getDescription());
            map.put("是否包邮", yxAdoptProduct.getIsPostage());
            map.put("获得积分", yxAdoptProduct.getGiveIntegral());
            map.put("成本价", yxAdoptProduct.getCost());
            map.put("是否优品推荐", yxAdoptProduct.getIsGood());
            map.put("虚拟销量", yxAdoptProduct.getFicti());
            map.put("浏览量", yxAdoptProduct.getBrowse());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    @Override
    public YxAdoptProduct saveProduct(YxAdoptProductDto adoptProduct) {
        if (adoptProduct.getAdoptCategory().getId() == null) {
            throw new BadRequestException("分类名称不能为空");
        }
        if (ObjectUtil.isEmpty(adoptProduct.getVarietyName())) {
            throw new BadRequestException("品种名称不能为空");
        }
//        boolean check = yxAdoptCategoryService
//                .checkProductCategory(adoptProduct.getAdoptCategory().getId());
//        if (!check) {
//            throw new BadRequestException("商品分类必选选择二级");
//        }
        adoptProduct.setCateId(adoptProduct.getAdoptCategory().getId().toString());
        final YxAdoptProduct yxAdoptProduct = BeanUtil.copyProperties(adoptProduct, YxAdoptProduct.class);
        // 添加商品
        this.save(yxAdoptProduct);
        this.updatePosition(yxAdoptProduct);
        return yxAdoptProduct;
    }

    @Override
    public void recovery(Integer id) {
        baseMapper.updateDel(0, id);
        baseMapper.updateOnsale(0, id);
    }

    @Override
    public void onSale(Integer id, int status) {
        if (status == 1) {
            status = 0;
        } else {
            status = 1;
        }
        baseMapper.updateOnsale(status, id);
    }

    @Override
    public List<ProductFormatDto> isFormatAttr(Integer id, String jsonStr) {
        if (ObjectUtil.isNull(id)) {
            throw new BadRequestException("产品不存在");
        }

        YxAdoptProductDto yxAdoptProductDTO = generator.convert(this.getById(id), YxAdoptProductDto.class);
        DetailDto detailDTO = attrFormat(jsonStr);
        List<ProductFormatDto> newList = new ArrayList<>();
        for (Map<String, Map<String, String>> map : detailDTO.getRes()) {
            ProductFormatDto productFormatDTO = new ProductFormatDto();
            productFormatDTO.setDetail(map.get("detail"));
            productFormatDTO.setCost(yxAdoptProductDTO.getCost().doubleValue());
            productFormatDTO.setPrice(yxAdoptProductDTO.getPrice().doubleValue());
            productFormatDTO.setSales(yxAdoptProductDTO.getSales());
            productFormatDTO.setPic(yxAdoptProductDTO.getImage());
            productFormatDTO.setCheck(false);
            newList.add(productFormatDTO);
        }
        return newList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createProductAttr(Long id, String jsonStr) {
//        JSONObject jsonObject = JSON.parseObject(jsonStr);
//        List<FromatDetailDto> attrList = JSON.parseArray(
//                jsonObject.get("items").toString(),
//                FromatDetailDto.class);
//        List<ProductFormatDto> valueList = JSON.parseArray(
//                jsonObject.get("attrs").toString(),
//                ProductFormatDto.class);
//
//
//        List<YxAdoptProductAttr> attrGroup = new ArrayList<>();
//        for (FromatDetailDto fromatDetailDTO : attrList) {
//            YxAdoptProductAttr yxAdoptProductAttr = new YxAdoptProductAttr();
//            yxAdoptProductAttr.setProductId(id);
//            yxAdoptProductAttr.setAttrName(fromatDetailDTO.getValue());
//            yxAdoptProductAttr.setAttrValues(StrUtil.
//                    join(",", fromatDetailDTO.getDetail()));
//            attrGroup.add(yxAdoptProductAttr);
//        }
//
//
//        List<YxAdoptProductAttrValue> valueGroup = new ArrayList<>();
//        for (ProductFormatDto productFormatDTO : valueList) {
//            YxAdoptProductAttrValue yxAdoptProductAttrValue = new YxAdoptProductAttrValue();
//            yxAdoptProductAttrValue.setProductId(id);
//            List<String> stringList = productFormatDTO.getDetail().values()
//                    .stream().collect(Collectors.toList());
//            Collections.sort(stringList);
//            yxAdoptProductAttrValue.setSku(StrUtil.
//                    join(",", stringList));
//            yxAdoptProductAttrValue.setPrice(BigDecimal.valueOf(productFormatDTO.getPrice()));
//            yxAdoptProductAttrValue.setCost(BigDecimal.valueOf(productFormatDTO.getCost()));
//            yxAdoptProductAttrValue.setStock(productFormatDTO.getSales());
//            yxAdoptProductAttrValue.setUnique(IdUtil.simpleUUID());
//            yxAdoptProductAttrValue.setImage(productFormatDTO.getPic());
//
//            valueGroup.add(yxAdoptProductAttrValue);
//        }
//
//        if (attrGroup.isEmpty() || valueGroup.isEmpty()) {
//            throw new BadRequestException("请设置至少一个属性!");
//        }
//
//        //如果设置sku 处理价格与库存
//
//        ////取最小价格
//        BigDecimal minPrice = valueGroup
//                .stream()
//                .map(YxAdoptProductAttrValue::getPrice)
//                .min(Comparator.naturalOrder())
//                .orElse(BigDecimal.ZERO);
//
//        //计算库存
//        Integer stock = valueGroup
//                .stream()
//                .map(YxAdoptProductAttrValue::getStock)
//                .reduce(Integer::sum)
//                .orElse(0);
//
//        YxAdoptProduct yxAdoptProduct = YxAdoptProduct.builder()
//                .stock(stock)
//                .price(minPrice)
//                .id(id)
//                .build();
//        this.updateById(yxAdoptProduct);
//
//        //插入之前清空
//        clearProductAttr(id, false);
//
//
//        //保存属性
//        yxAdoptProductAttrService.saveOrUpdateBatch(attrGroup);
//
//        //保存值
//        yxAdoptProductAttrValueService.saveOrUpdateBatch(valueGroup);
//
//        Map<String, Object> map = new LinkedHashMap<>();
//        map.put("attr", jsonObject.get("items"));
//        map.put("value", jsonObject.get("attrs"));
//
//        //保存结果
//        setResult(map, id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void setResult(Map<String, Object> map, Long id) {
//        YxAdoptProductAttrResult yxAdoptProductAttrResult = new YxAdoptProductAttrResult();
//        yxAdoptProductAttrResult.setProductId(id);
//        yxAdoptProductAttrResult.setResult(JSON.toJSONString(map));
//        yxAdoptProductAttrResult.setChangeTime(new Date());
//
//        yxAdoptProductAttrResultService.remove(new LambdaQueryWrapper<YxAdoptProductAttrResult>().eq(YxAdoptProductAttrResult::getProductId, id));
//
//        yxAdoptProductAttrResultService.saveOrUpdate(yxAdoptProductAttrResult);
    }

    @Override
    public String getAdoptProductAttrResult(Integer id) {
//        YxAdoptProductAttrResult yxAdoptProductAttrResult = yxAdoptProductAttrResultService
//                .getOne(new LambdaQueryWrapper<YxAdoptProductAttrResult>().eq(YxAdoptProductAttrResult::getProductId, id));
//        if (ObjectUtil.isNull(yxAdoptProductAttrResult)) {
//            return "";
//        }
//        return yxAdoptProductAttrResult.getResult();
        return "";
    }

    @Override
    public void updateProduct(YxAdoptProduct resources) {
        if (resources.getAdoptCategory() == null || resources.getAdoptCategory().getId() == null) {
            throw new BadRequestException("请选择分类");
        }
        if (ObjectUtil.isEmpty(resources.getVarietyName())) {
            throw new BadRequestException("品种名称不能为空");
        }
//        boolean check = yxAdoptCategoryService
//                .checkProductCategory(resources.getAdoptCategory().getId());
//        if (!check) {
//            throw new BadRequestException("商品分类必选选择二级");
//        }
        resources.setCateId(resources.getAdoptCategory().getId().toString());
        this.saveOrUpdate(resources);
        this.updatePosition(resources);
    }
    public void updatePosition(YxAdoptProduct adoptProduct) {
        if (ObjectUtil.isNotEmpty(adoptProduct.getId())){
            String ss1 = "POINT(" + adoptProduct.getPositionStr().replace(",", " ") + ")";
            this.baseMapper.updatePosition(ss1, adoptProduct.getId().toString());
        }
    }
    @Override
    public void delete(Integer id) {
        baseMapper.updateDel(1, id);
    }

    @Override
    public YxAdoptProduct getGoodsByIdFromCache(Long id) {
        //获取缓存中的商品
        YxAdoptProduct goods =  (YxAdoptProduct) cache.get(YxAdoptProductService.getCacheKeys(id.toString()));
        //如果缓存中没有信息，则查询数据库，然后写入缓存
        if (goods== null) {
            goods = this.getById(id);
            if (goods == null) {
                return null;
            }
            cache.put(YxAdoptProductService.getCacheKeys(id.toString()), goods);
        }
        //获取商品库存
        Integer integer =  (Integer) cache.get(YxAdoptProductService.getStockCacheKey(id.toString()));
        //库存不为空,库存与缓存中不一致
        if (integer != null && !goods.getStock().equals(integer)) {
            //写入最新的库存信息
            cache.put(YxAdoptProductService.getCacheKeys(goods.getId().toString()), goods);
            cache.put(YxAdoptProductService.getStockCacheKey(id.toString()),goods.getStock());
        }
        return goods;
    }

    @Override
    public Integer getStock(String goodsId) {
        String cacheKeys = YxAdoptProductService.getStockCacheKey(goodsId);
        Integer stock = (Integer) cache.get(cacheKeys);
        if (stock != null) {
            return stock;
        } else {
            YxAdoptProduct goods = getGoodsByIdFromCache(Long.parseLong(goodsId));
            cache.put(cacheKeys, goods.getStock());
            return goods.getStock();
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void clearProductAttr(Long id, boolean isActice) {
        if (ObjectUtil.isNull(id)) {
            throw new BadRequestException("产品不存在");
        }
//        yxAdoptProductAttrService.remove(new LambdaQueryWrapper<YxAdoptProductAttr>().eq(YxAdoptProductAttr::getProductId, id));
//        yxAdoptProductAttrValueService.remove(new LambdaQueryWrapper<YxAdoptProductAttrValue>().eq(YxAdoptProductAttrValue::getProductId, id));
//
//        if (isActice) {
//            yxAdoptProductAttrResultService.remove(new LambdaQueryWrapper<YxAdoptProductAttrResult>().eq(YxAdoptProductAttrResult::getProductId, id));
//        }
    }

    /**
     * 组合规则属性算法
     * @param jsonStr
     * @return
     */
    public DetailDto attrFormat(String jsonStr) {
        JSONObject jsonObject = JSON.parseObject(jsonStr);
        List<FromatDetailDto> fromatDetailDTOList = JSON.parseArray(jsonObject.get("items").toString(),
                FromatDetailDto.class);
        List<String> data = new ArrayList<>();
        List<Map<String, Map<String, String>>> res = new ArrayList<>();
        if (fromatDetailDTOList.size() > 1) {
            for (int i = 0; i < fromatDetailDTOList.size() - 1; i++) {
                if (i == 0) {
                    data = fromatDetailDTOList.get(i).getDetail();
                }
                List<String> tmp = new LinkedList<>();
                for (String v : data) {
                    for (String g : fromatDetailDTOList.get(i + 1).getDetail()) {
                        String rep2 = "";
                        if (i == 0) {
                            rep2 = fromatDetailDTOList.get(i).getValue() + "_" + v + "-"
                                    + fromatDetailDTOList.get(i + 1).getValue() + "_" + g;
                        } else {
                            rep2 = v + "-"
                                    + fromatDetailDTOList.get(i + 1).getValue() + "_" + g;
                        }
                        tmp.add(rep2);
                        if (i == fromatDetailDTOList.size() - 2) {
                            Map<String, Map<String, String>> rep4 = new LinkedHashMap<>();
                            Map<String, String> reptemp = new LinkedHashMap<>();
                            for (String h : Arrays.asList(rep2.split("-"))) {
                                List<String> rep3 = Arrays.asList(h.split("_"));

                                if (rep3.size() > 1) {
                                    reptemp.put(rep3.get(0), rep3.get(1));
                                } else {
                                    reptemp.put(rep3.get(0), "");
                                }
                            }
                            rep4.put("detail", reptemp);
                            res.add(rep4);
                        }
                    }
                }
                if (!tmp.isEmpty()) {
                    data = tmp;
                }
            }
        } else {
            List<String> dataArr = new ArrayList<>();

            for (FromatDetailDto fromatDetailDTO : fromatDetailDTOList) {

                for (String str : fromatDetailDTO.getDetail()) {
                    Map<String, Map<String, String>> map2 = new LinkedHashMap<>();
                    //List<Map<String,String>> list1 = new ArrayList<>();
                    dataArr.add(fromatDetailDTO.getValue() + "_" + str);
                    Map<String, String> map1 = new LinkedHashMap<>();
                    map1.put(fromatDetailDTO.getValue(), str);
                    //list1.add(map1);
                    map2.put("detail", map1);
                    res.add(map2);
                }
            }
            String s = StrUtil.join("-", dataArr);
            data.add(s);
        }
        DetailDto detailDTO = new DetailDto();
        detailDTO.setData(data);
        detailDTO.setRes(res);
        return detailDTO;
    }
}
